<?php
/**
 * @desc 支付宝.退款
 * @document https://docs.open.alipay.com/api_1/alipay.trade.refund/
 * @author Vincent
 */

namespace young\payment;

use young\Common;

class AliRefund extends AliConfig
{
    public function run($data)
    {
        $this->setConfig($data['config']);
        return $this->handle($data['order_sn'], $data['refund_amount'], $data['refund_sn']);
    }

    /**
     * @param $orderSn 商户订单号
     * @param $refundAmount 退款金额
     * @param $refundSn 退款订单号
     * @return bool
     * @throws \Exception
     */
    private function handle($orderSn, $refundAmount, $refundSn)
    {
        $common = [];
        $common['app_id'] = $this->appId;
        $common['method'] = 'alipay.trade.refund';
        $common['format'] = self::FORMAT;
        $common['charset'] = self::CHARSET;
        $common['sign_type'] = self::SIGN_TYPE;
        $common['timestamp'] = date('Y-m-d H:i:s', time());
        $common['version'] = self::VERSION;
        $common['biz_content'] = [];
        $common['biz_content']['out_trade_no'] = $orderSn;
        $common['biz_content']['refund_amount'] = $refundAmount;
        $common['biz_content']['out_request_no'] = $refundSn;
        $common['biz_content'] = json_encode($common['biz_content'], JSON_UNESCAPED_UNICODE);
        $common = array_filter($common);

        ksort($common);

        $rsa2 = new AliRsa2;

        //签名
        $rsa2->setKey($rsa2->getRsaKeyValue($this->rsaPrivateKey, 'private'));
        $common['sign'] = $rsa2->encrypt(urldecode(http_build_query($common)));

        $common = $rsa2->splicingString($common);
        $result = Common::request_get(self::GETEWAY_URL . '?' . $common);
        $result = json_decode($result, true);
        $data = $result['alipay_trade_refund_response'];

        //验证签名
        $rsa2->setKey($rsa2->getRsaKeyValue($this->aliPublicKey, 'public'));
        $verifySign = $rsa2->rsaVerify(json_encode($data, JSON_UNESCAPED_UNICODE), $result['sign']);

        if ($verifySign === true) {
            if ($data['code'] == '10000') {
                if ($data['fund_change'] == 'Y') {
                    //退款成功
                    return true;
                } else {
                    throw new \Exception('本次退款没有发生资金变化');
                }
            } else {
                throw new \Exception('[code:' . $data['code'] . '][msg:' . $data['msg'] . ']');
            }
        } else {
            throw new \Exception('签名失败');
        }
    }
}